home *** CD-ROM | disk | FTP | other *** search
- unit NewParse;
-
- interface
-
- uses
- Classes, SysUtils, Consts;
-
- const
- toComment = Char(5);
-
- type
- TNewParser = class(TObject)
- private
- FStream: TStream;
- FOrigin: Longint;
- FBuffer: PChar;
- FBufPtr: PChar;
- FBufEnd: PChar;
- FSourcePtr: PChar;
- FSourceEnd: PChar;
- FTokenPtr: PChar;
- FStringPtr: PChar;
- FSourceLine: Integer;
- FSaveChar: Char;
- FToken: Char;
- procedure ReadBuffer;
- procedure SkipBlanks;
- public
- constructor Create(Stream: TStream);
- destructor Destroy; override;
- procedure CheckToken(T: Char);
- procedure CheckTokenSymbol(const S: string);
- procedure Error(const Ident: string);
- procedure ErrorFmt(const Ident: string; const Args: array of const);
- procedure ErrorStr(const Message: string);
- procedure HexToBinary(Stream: TStream);
- function NextToken: Char;
- function SourcePos: Longint;
- function TokenComponentIdent: String;
- function TokenFloat: Extended;
- function TokenInt: Longint;
- function TokenString: string;
- function TokenSymbolIs(const S: string): Boolean;
- property SourceLine: Integer read FSourceLine;
- property Token: Char read FToken;
- end;
-
- implementation
-
- const
- ParseBufSize = 4096;
-
- {procedure BinToHex(Buffer, Text: PChar; BufSize: Integer); assembler;
- asm
- PUSH ESI
- PUSH EDI
- MOV ESI,EAX
- MOV EDI,EDX
- MOV EDX,0
- JMP @@1
- @@0: DB '0123456789ABCDEF'
- @@1: LODSB
- MOV DL,AL
- AND DL,0FH
- MOV AH,@@0.Byte[EDX]
- MOV DL,AL
- SHR DL,4
- MOV AL,@@0.Byte[EDX]
- STOSW
- DEC ECX
- JNE @@1
- POP EDI
- POP ESI
- end;}
-
- function HexToBin(Text, Buffer: PChar; BufSize: Integer): Integer; assembler;
- asm
- PUSH ESI
- PUSH EDI
- PUSH EBX
- MOV ESI,EAX
- MOV EDI,EDX
- MOV EBX,EDX
- MOV EDX,0
- JMP @@1
- @@0: DB 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
- DB -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
- DB -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
- DB -1,10,11,12,13,14,15
- @@1: LODSW
- CMP AL,'0'
- JB @@2
- CMP AL,'f'
- JA @@2
- MOV DL,AL
- MOV AL,@@0.Byte[EDX-'0']
- CMP AL,-1
- JE @@2
- SHL AL,4
- CMP AH,'0'
- JB @@2
- CMP AH,'f'
- JA @@2
- MOV DL,AH
- MOV AH,@@0.Byte[EDX-'0']
- CMP AH,-1
- JE @@2
- OR AL,AH
- STOSB
- DEC ECX
- JNE @@1
- @@2: MOV EAX,EDI
- SUB EAX,EBX
- POP EBX
- POP EDI
- POP ESI
- end;
-
- constructor TNewParser.Create(Stream: TStream);
- begin
- FStream := Stream;
- GetMem(FBuffer, ParseBufSize);
- FBuffer[0] := #0;
- FBufPtr := FBuffer;
- FBufEnd := FBuffer + ParseBufSize;
- FSourcePtr := FBuffer;
- FSourceEnd := FBuffer;
- FTokenPtr := FBuffer;
- FSourceLine := 1;
- NextToken;
- end;
-
- destructor TNewParser.Destroy;
- begin
- if FBuffer <> nil then
- begin
- FStream.Seek(Longint(FTokenPtr) - Longint(FBufPtr), 1);
- FreeMem(FBuffer, ParseBufSize);
- end;
- end;
-
- procedure TNewParser.CheckToken(T: Char);
- begin
- if Token <> T then
- case T of
- toSymbol:
- Error(SIdentifierExpected);
- toString:
- Error(SStringExpected);
- toInteger, toFloat:
- Error(SNumberExpected);
- else
- ErrorFmt(SCharExpected, [T]);
- end;
- end;
-
- procedure TNewParser.CheckTokenSymbol(const S: string);
- begin
- if not TokenSymbolIs(S) then ErrorFmt(SSymbolExpected, [S]);
- end;
-
- procedure TNewParser.Error(const Ident: string);
- begin
- ErrorStr(Ident);
- end;
-
- procedure TNewParser.ErrorFmt(const Ident: string; const Args: array of const);
- begin
- ErrorStr(Format(Ident, Args));
- end;
-
- procedure TNewParser.ErrorStr(const Message: string);
- begin
- raise EParserError.CreateFmt(SParseError, [Message, FSourceLine]);
- end;
-
- procedure TNewParser.HexToBinary(Stream: TStream);
- var
- Count: Integer;
- Buffer: array[0..255] of Char;
- begin
- SkipBlanks;
- while FSourcePtr^ <> '}' do
- begin
- Count := HexToBin(FSourcePtr, Buffer, SizeOf(Buffer));
- if Count = 0 then Error(SInvalidBinary);
- Stream.Write(Buffer, Count);
- Inc(FSourcePtr, Count * 2);
- SkipBlanks;
- end;
- NextToken;
- end;
-
- function TNewParser.NextToken: Char;
- var
- I: Integer;
- P, S: PChar;
- begin
- SkipBlanks;
- P := FSourcePtr;
- FTokenPtr := P;
- case P^ of
- 'A'..'Z', 'a'..'z', '_':
- begin
- Inc(P);
- while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
- Result := toSymbol;
- end;
- '#', '''':
- begin
- S := P;
- while True do
- case P^ of
- '#':
- begin
- Inc(P);
- I := 0;
- while P^ in ['0'..'9'] do
- begin
- I := I * 10 + (Ord(P^) - Ord('0'));
- Inc(P);
- end;
- S^ := Chr(I);
- Inc(S);
- end;
- '''':
- begin
- Inc(P);
- while True do
- begin
- case P^ of
- #0, #10, #13:
- Error(SInvalidString);
- '''':
- begin
- Inc(P);
- if P^ <> '''' then Break;
- end;
- end;
- S^ := P^;
- Inc(S);
- Inc(P);
- end;
- end;
- else
- Break;
- end;
- FStringPtr := S;
- Result := toString;
- end;
- '$':
- begin
- Inc(P);
- while P^ in ['0'..'9', 'A'..'F', 'a'..'f'] do Inc(P);
- Result := toInteger;
- end;
- '-', '0'..'9':
- begin
- Inc(P);
- while P^ in ['0'..'9'] do Inc(P);
- Result := toInteger;
- while P^ in ['0'..'9', '.', 'e', 'E', '+', '-'] do
- begin
- Inc(P);
- Result := toFloat;
- end;
- end;
- // new custom code!!!!
- '{':
- begin
- // look for closing brace
- while (P^ <> '}') and (P^ <> toEOF) do ////////////// bug
- Inc(P);
- // move to the next
- if (P^ <> toEOF) then
- Inc(P);
- Result := toComment;
- end;
- else
- // updated
- if (P^ = '/') and (P^ <> toEOF) and ((P+1)^ = '/') then
- begin
- // single line comment
- while P^ <> #13 do
- Inc(P);
- Result := toComment;
- end
- else
- begin
- Result := P^;
- if Result <> toEOF then
- Inc(P);
- end;
- end;
- FSourcePtr := P;
- FToken := Result;
- end;
-
- procedure TNewParser.ReadBuffer;
- var
- Count: Integer;
- begin
- Inc(FOrigin, FSourcePtr - FBuffer);
- FSourceEnd[0] := FSaveChar;
- Count := FBufPtr - FSourcePtr;
- if Count <> 0 then Move(FSourcePtr[0], FBuffer[0], Count);
- FBufPtr := FBuffer + Count;
- Inc(FBufPtr, FStream.Read(FBufPtr[0], FBufEnd - FBufPtr));
- FSourcePtr := FBuffer;
- FSourceEnd := FBufPtr;
- if FSourceEnd = FBufEnd then
- begin
- FSourceEnd := LineStart(FBuffer, FSourceEnd - 1);
- if FSourceEnd = FBuffer then Error(SLineTooLong);
- end;
- FSaveChar := FSourceEnd[0];
- FSourceEnd[0] := #0;
- end;
-
- procedure TNewParser.SkipBlanks;
- begin
- while True do
- begin
- case FSourcePtr^ of
- #0:
- begin
- ReadBuffer;
- if FSourcePtr^ = #0 then Exit;
- Continue;
- end;
- #10:
- Inc(FSourceLine);
- #33..#255:
- Exit;
- end;
- Inc(FSourcePtr);
- end;
- end;
-
- function TNewParser.SourcePos: Longint;
- begin
- Result := FOrigin + (FTokenPtr - FBuffer);
- end;
-
- function TNewParser.TokenFloat: Extended;
- begin
- Result := StrToFloat(TokenString);
- end;
-
- function TNewParser.TokenInt: Longint;
- begin
- Result := StrToInt(TokenString);
- end;
-
- function TNewParser.TokenString: string;
- var
- L: Integer;
- begin
- if FToken = toString then
- L := FStringPtr - FTokenPtr else
- L := FSourcePtr - FTokenPtr;
- SetString(Result, FTokenPtr, L);
- end;
-
- function TNewParser.TokenSymbolIs(const S: string): Boolean;
- begin
- Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
- end;
-
- function TNewParser.TokenComponentIdent: String;
- var
- P: PChar;
- begin
- CheckToken(toSymbol);
- P := FSourcePtr;
- while P^ = '.' do
- begin
- Inc(P);
- if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
- Error(SIdentifierExpected);
- repeat
- Inc(P)
- until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
- end;
- FSourcePtr := P;
- Result := TokenString;
- end;
-
- end.
-